<template>
	<view class="upload-file">
		<!-- 文件列表 -->
		<view class="file-list" v-if="props.modelValue.length > 0">
			<view v-for="(file, index) in props.modelValue" :key="index" class="file-item">
				<!-- 进度遮罩层 -->
				<view v-if="uploadProgress[file] !== undefined" class="progress-overlay">
					<progress class="progress-bar" :value="uploadProgress[file]" max="100" />
					<text class="progress-text">{{ uploadProgress[file] }}%</text>
				</view>

				<!-- 修改预览部分 -->
				<view v-if="isVideo(file)" class="media-wrapper" @click="handlePreview(file)">
					<image :src="file + '?vframe/jpg/offset/0'" class="media-content" mode="aspectFill" />
					<view class="play-wrapper">
						<image src="/static/icons/play.svg" class="play-icon" />
					</view>
				</view>
				<image v-else :src="file" mode="aspectFill" class="media-content" @click="handlePreview(file)" />

				<!-- 上传完成显示删除按钮 -->
				<image v-if="uploadProgress[file] === undefined" src="/static/icons/close.svg" class="delete-icon"
					@click="handleDelete(index)" />
			</view>
		</view>

		<!-- 使用封装的 DragUploadArea 组件 -->
		<DragUploadArea :modelValue="props.modelValue" :maxCount="props.maxCount" :accept="props.accept"
			@triggerUpload="triggerUpload" @handleFiles="handleFiles" @error="handleError" />

		<!-- 自定义加载提示 -->
		<view v-if="uploading" class="upload-loading">
			<text class="loading-text">上传中...</text>
		</view>

		<MediaPreview v-if="previewUrl" :url="previewUrl" @close="previewUrl = ''" />
	</view>
</template>

<script setup>
import { ref, computed } from 'vue'
import MediaPreview from '../preview/MediaPreview.vue'
import DragUploadArea from './DragUploadArea.vue' // 引入封装的上传区域组件

const previewUrl = ref('')
import { request } from '@/utils/request'

const UPLOAD_URL = 'https://jsz315.xyz/uni-record/upload'

const uploading = ref(false)
const uploadProgress = ref({})

const props = defineProps({
	modelValue: {
		type: Array,
		default: () => []
	},
	maxCount: {
		type: Number,
		default: 9
	},
	accept: {
		type: String,
		default: 'image/*,video/*'
	}
})

const emit = defineEmits(['update:modelValue', 'error'])

const triggerUpload = () => {
	if (props.modelValue.length >= props.maxCount) {
		emit('error', `最多上传 ${props.maxCount} 个文件`)
		return
	}

	// #ifdef H5
	const input = document.createElement('input')
	input.type = 'file'
	input.accept = props.accept
	input.multiple = true
	input.onchange = (e) => handleFiles(e.target.files)
	input.click()
	// #endif

	// #ifdef APP-PLUS
	uni.chooseImage({
		count: props.maxCount - props.modelValue.length,
		sourceType: ['album', 'camera'],
		success: (res) => {
			uploadFiles(res.tempFilePaths)
		},
		fail: (err) => {
			console.error('选择图片失败:', err)
			emit('error', '选择文件失败')
		}
	})
	// #endif

	// #ifdef MP-WEIXIN
	uni.chooseMedia({
		count: props.maxCount - props.modelValue.length,
		mediaType: ['image', 'video'],
		sourceType: ['album', 'camera'],
		maxDuration: 60,
		success: (res) => {
			const files = res.tempFiles.map(file => file.tempFilePath)
			uploadFiles(files)
		},
		fail: (err) => emit('error', '选择文件失败')
	})
	// #endif
}

const uploadFiles = async (fileList) => {
	uploading.value = true
	try {
		// 先一次性添加所有文件到 modelValue
		const newModelValue = [...props.modelValue]
		fileList.forEach(tempFilePath => {
			if (newModelValue.length < props.maxCount) {
				newModelValue.push(tempFilePath)
				uploadProgress.value[tempFilePath] = 0
			}
		})
		emit('update:modelValue', newModelValue)

		// 然后逐个上传
		for (const tempFilePath of fileList) {
			if (props.modelValue.length >= props.maxCount) break

			const uploadTask = uni.uploadFile({
				url: UPLOAD_URL,
				filePath: tempFilePath,
				name: 'file',
				formData: {
					userId: '123'
				},
				success: (res) => {
					const result = JSON.parse(res.data)
					if (result.code === 0) {
						const newModelValue = props.modelValue.map(item =>
							item === tempFilePath ? result.data.path : item
						)
						emit('update:modelValue', newModelValue)
						delete uploadProgress.value[tempFilePath]
						uploadProgress.value = {
							...uploadProgress.value
						}
					}
				},
				fail: (err) => {
					console.error('上传失败:', err)
					emit('error', '文件上传失败')
				}
			})

			uploadTask.onProgressUpdate((res) => {
				uploadProgress.value[tempFilePath] = res.progress
				uploadProgress.value = {
					...uploadProgress.value
				}
			})
		}
	} finally {
		uploading.value = false
	}
}

const handleFiles = async (files) => {
	uploading.value = true
	try {
		const fileArray = Array.from(files)
		const newModelValue = [...props.modelValue]

		for (const file of fileArray) {
			if (newModelValue.length >= props.maxCount) break
			if (!file.type.match(/^(image|video)\//)) continue

			const previewURL = URL.createObjectURL(file)
			newModelValue.push(previewURL)
			uploadProgress.value = {
				...uploadProgress.value,
				[previewURL]: 0
			}

			const formData = new FormData()
			formData.append('file', file)

			const xhr = new XMLHttpRequest()
			xhr.open('POST', UPLOAD_URL)
			xhr.upload.onprogress = (e) => {
				if (e.lengthComputable) {
					const progress = Math.round((e.loaded / e.total) * 100)
					uploadProgress.value[previewURL] = progress
					uploadProgress.value = {
						...uploadProgress.value
					}
				}
			}
			xhr.onload = () => {
				console.log('XHR Status:', xhr.status);
				console.log('XHR Response:', xhr.responseText);
				try {
					if (xhr.status >= 200 && xhr.status < 300) {
						const result = JSON.parse(xhr.responseText);
						console.log('Upload result:', result);
						if (result.code === 0) {
							const updatedModelValue = newModelValue.map(item =>
								item === previewURL ? result.data.path : item
							);
							emit('update:modelValue', updatedModelValue);
							delete uploadProgress.value[previewURL];
							uploadProgress.value = {
								...uploadProgress.value
							};
						} else {
							throw new Error(result.message || '上传失败');
						}
					} else {
						throw new Error(`HTTP错误: ${xhr.status}`);
					}
				} catch (error) {
					console.error('Upload error:', error);
					emit('error', error.message || '文件上传失败');
				}
			};

			xhr.onerror = (error) => {
				console.error('XHR Error:', error);
				emit('error', '网络错误，上传失败');
			};

			xhr.send(formData)
		}

		emit('update:modelValue', newModelValue)
	} catch (error) {
		console.error('Upload error:', error)
		emit('error', '文件上传失败')
	} finally {
		uploading.value = false
	}
}

const handleDelete = (index) => {
	const newFiles = [...props.modelValue]
	newFiles.splice(index, 1)
	emit('update:modelValue', newFiles)
}

const isVideo = (file) => {
	return file.match(/\.(mp4|webm|ogg|mov)$/i)
}

const handlePreview = (url) => {
	previewUrl.value = url
}

const handleError = (message) => {
	emit('error', message)
}
</script>

<style scoped>
/* 其他样式保持不变 */
.upload-file {
	margin-top: 12rpx;
}

.file-list {
	display: flex;
	flex-wrap: wrap;
	gap: 20rpx;
	margin-bottom: 20rpx;
}

.file-item {
	position: relative;
	width: 200rpx;
	height: 200rpx;
	border-radius: 8rpx;
	overflow: hidden;
	box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
	background: rgba(0, 0, 0, 0.1);
}

.media-wrapper {
	position: relative;
	width: 100%;
	height: 100%;
}

.media-content {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.play-wrapper {
	position: absolute;
	left: 50%;
	top: 50%;
	transform: translate(-50%, -50%);
	width: 90rpx;
	height: 90rpx;
	border-radius: 50%;
	display: flex;
	align-items: center;
	justify-content: center;
}

.play-icon {
	width: 100%;
	height: 100%;
}

.delete-icon {
	position: absolute;
	right: 8rpx;
	top: 8rpx;
	width: 36rpx;
	height: 36rpx;
	z-index: 1;
}

.preview-video {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.delete-icon {
	position: absolute;
	right: 8rpx;
	top: 8rpx;
	color: #fff;
	background: rgba(255, 0, 0, 0.8);
	border-radius: 50%;
	width: 36rpx;
	height: 36rpx;
	text-align: center;
	line-height: 36rpx;
	font-size: 28rpx;
	font-weight: bold;
}

.upload-loading {
	margin-top: 20rpx;
	text-align: center;
	color: #409eff;
	font-size: 28rpx;
}

.loading-text {
	animation: blink 1.5s infinite;
}

@keyframes blink {
	0% {
		opacity: 1;
	}

	50% {
		opacity: 0.5;
	}

	100% {
		opacity: 1;
	}
}
</style>